package web

import (
	"github.com/gin-gonic/gin"
	"github.com/wechatpay-apiv3/wechatpay-go/core/notify"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
	"net/http"
	"webook/payment/service/wechat"
	"webook/pkg/logger"
)

type WechatHandler struct {
	handler   *notify.Handler
	l         logger.LoggerV1
	nativeSvc *wechat.NativePaymentService
}

func NewWechatHandler(handler *notify.Handler, nativeSvc *wechat.NativePaymentService, l logger.LoggerV1) *WechatHandler {
	return &WechatHandler{
		handler:   handler,
		nativeSvc: nativeSvc,
		l:         l,
	}
}

func (h *WechatHandler) RegisterRoutes(server *gin.Engine) {
	server.Any("/pay/callback", h.HandleNative)
}

func (h *WechatHandler) HandleNative(ctx *gin.Context) {
	// 用来接收解密后的数据的
	transaction := new(payments.Transaction)
	_, err := h.handler.ParseNotifyRequest(ctx, ctx.Request, transaction)
	if err != nil {
		ctx.String(http.StatusBadRequest, "参数解析失败")
		h.l.Error("解析微信支付回调失败", logger.Error(err))
		// 在这里， 你可以考虑进一步加监控和告警 绝大概率是黑客在尝试攻击你
		return
	}
	//可以考虑 发送到 Kafka 也可以考虑直接处理
	/*
		一般采用这种设计的缘由是：
		收到消息之后，转发到 Kafka，那么如果有别的部门也关心这个回调，他们就可以去订阅这个消息。
		转发到 Kafka 之后，整个重试之类的机制就在我们的控制之下了。
		DEBUG 比较简单。payment-web 本身只承担了轻量的解密功能，在遇到问题的时候可以直接绕开payment-web，在 Kakfa 中重发消息，或者模拟一个消息来测试代码。
		削峰。聊胜于无，毕竟理论上来说，这边回调过来的QPS 和你正向支付的 QPS 是保持一致的，也就是说你正向支付撑得住这些流量，没道理处理回调的时候撑不住。秒杀之类的场景可能会比较好。
	*/
	err = h.nativeSvc.HandleCallback(ctx, transaction)
	if err != nil {
		ctx.String(http.StatusInternalServerError, "系统异常")
		// 处理回调失败 可以考虑触发对账
		h.l.Error("处理微信支付回调失败", logger.Error(err), logger.String("biz_trade_no", *transaction.OutTradeNo))
		return
	}
	ctx.String(http.StatusOK, "OK")
}
